/*******************************************************************************
 * Copyright (c) 2011 EclipseDevX.org and others.
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at:
 * 
 *     http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package org.eclipsedevx.metrics.model;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipsedevx.metrics.DevXMetricsPlugin;

// TODO: test renaming projects

/**
 * 
 * 
 * @author dcarew
 */
public class ProjectHistory {
    private Map<IProject, MetricsHistory> projectHistory = new HashMap<IProject, MetricsHistory>();
    
    private IPath savePath;
    
    public ProjectHistory() {
        
    }

    public void loadFrom(IPath savePath) throws IOException {
        this.savePath = savePath;
        
        File inFile = savePath.toFile();
        
        if (inFile.exists()) {
        	loadFrom(new FileInputStream(inFile));
        }
    }
    
	public void updateMetrics(IProject project, MetricsData data) {
        MetricsHistory history = projectHistory.get(project);
        
        if (history == null) {
            history = new MetricsHistory();
            
            projectHistory.put(project, history);
        }
        
        history.add(DayCode.today().getCode(), data.getValueAsInt(MetricsData.JAVA_SLOC));
    }

    public void removeProject(IProject project) {
        projectHistory.put(project, null);
    }

    public void save() {
        try {
            File tempFile = File.createTempFile("metrics", "history", savePath.toFile().getParentFile());
            tempFile.deleteOnExit();
            
            saveTo(new FileOutputStream(tempFile));
            
            replaceFile(savePath, tempFile);
            
            tempFile.delete();
        } catch (IOException ioe) {
            DevXMetricsPlugin.logError(ioe);
        }
    }

	public MetricsHistory getMetricsHistory(List<IProject> projects) {
        List<MetricsHistory> histories = new ArrayList<MetricsHistory>();
        
        for (IProject project : projects) {
        	MetricsHistory history = projectHistory.get(project);
        	
        	if (history != null) {
        		histories.add(history);
        	}
        }
        
        if (histories.size() == 0) {
        	return null;
        } else {
        	return MetricsHistory.combine(histories);
        }
    }

    private void loadFrom(InputStream in) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
		
		String line = reader.readLine();
		
		while (line != null) {
			if (line.length() > 0) {
				String[] split1 = line.split("=");
				
				String projectName = split1[0];
				
				String[] data = split1[1].split(",");
				
				IProject project = getProject(projectName);
				
				if (project != null) {
					projectHistory.put(project, createMetricsHistory(data));
				}
			}
			
			line = reader.readLine();
		}
    	
		reader.close();
	}

    private IProject getProject(String projectName) {
    	return ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
	}

	private MetricsHistory createMetricsHistory(String[] tuples) {
		MetricsHistory history = new MetricsHistory();
		
		for (String tuple : tuples) {
			String[] data = tuple.split(":");
			
			history.add(data[0], Integer.parseInt(data[1]));
		}
		
		return history;
	}

	private void saveTo(OutputStream fout) throws IOException {
		PrintStream out = new PrintStream(fout, false, "UTF-8");
    	
		for (IProject project : projectHistory.keySet()) {
			if (project.exists() && projectHistory.get(project) != null) {
				out.print(project.getName() + "=");
				
				MetricsHistory history = projectHistory.get(project);
				Map<String, Integer> values = history.getValues();
				
				StringBuilder builder = new StringBuilder();
				
				for (String dayCode : values.keySet()) {
					// TODO: trim out older dates (6 months? 2 years?)
					
					if (builder.length() > 0) {
						builder.append(',');
					}
					
					builder.append(dayCode + ":" + values.get(dayCode));
				}
				
				out.println(builder.toString());
			}
		}
		
		out.println();
		out.close();
	}

	private void replaceFile(IPath toReplacePath, File replaceWithFile) throws IOException {
		InputStream in = new FileInputStream(replaceWithFile);
		OutputStream out = new FileOutputStream(toReplacePath.toFile());
		
		byte[] buffer = new byte[10240];
		
		int count = in.read(buffer);
		
		while (count > 0) {
			out.write(buffer, 0, count);
			count = in.read(buffer);
		}

		out.close();
		in.close();
	}

}
